# Decompiled with PyLingual (https://pylingual.io)
# Internal filename: aidkc7.py
# Bytecode version: 3.11a7e (3495)
# Source timestamp: 1970-01-01 00:00:00 UTC (0)

import uiautomator2 as u2
import time
import os
import datetime
import subprocess
import logging
import random
from typing import Optional, Dict

class Config:
    MI_HOME_PACKAGE = 'com.xiaomi.smarthome'
    MAIN_ACTIVITY = '.SmartHomeMainActivity'
    DEFAULT_SCREENSHOT_DIR = './screenshots'
    LOG_FORMAT = '%(asctime)s - %(levelname)s - %(message)s'

class MiHomeTester:
    def __init__(self, device_id: str, lock_name: str):
        self.d = u2.connect(device_id)
        self.lock_name = lock_name
        self.logger = self._setup_logger()
        self._prepare_dirs()

    def _setup_logger(self) -> logging.Logger:
        """配置日志系统"""  # inserted
        logger = logging.getLogger(__name__)
        logger.setLevel(logging.INFO)
        file_name = datetime.datetime.now().strftime('%Y%m%d%H%M') + '_automation.log'
        file_handler = logging.FileHandler(file_name)
        file_handler.setFormatter(logging.Formatter(Config.LOG_FORMAT))
        console_handler = logging.StreamHandler()
        console_handler.setFormatter(logging.Formatter(Config.LOG_FORMAT))
        logger.addHandler(file_handler)
        logger.addHandler(console_handler)
        return logger

    def _prepare_dirs(self):
        """创建必要目录"""  # inserted
        os.makedirs(Config.DEFAULT_SCREENSHOT_DIR, exist_ok=True)

    def screenshot(self, sub_dir: str='default') -> str:
        """通用截图方法"""  # inserted
        timestamp = datetime.datetime.now().strftime('%Y%m%d_%H%M%S')
        dir_path = os.path.join(Config.DEFAULT_SCREENSHOT_DIR, sub_dir)
        os.makedirs(dir_path, exist_ok=True)
        save_path = os.path.join(dir_path, f'{timestamp}.jpg')
        self.d.screenshot().save(save_path)
        self.logger.info(f'Screenshot saved: {save_path}')
        return save_path

    def safe_click(self, selector: Dict, timeout: int=10) -> bool:
        """安全点击控件（修正版）"""  # inserted
        try:
            if self.d(**selector).wait(timeout):
                element = self.d(**selector)
                element.click()
                return True
            self.logger.warning(f'元素未找到: {selector}')
            return False
        except Exception as e:
            self.logger.error(f'点击失败: {str(e)}')
            return False

    def open_mihome(self) -> bool:
        """启动米家APP"""  # inserted
        try:
            subprocess.run(['adb', 'shell', 'am', 'force-stop', Config.MI_HOME_PACKAGE], check=True)
            self.d.app_start(Config.MI_HOME_PACKAGE, activity=Config.MAIN_ACTIVITY, stop=True, wait=True)
            self.d.wait_activity('.SmartHomeMainActivity')
            if self.d(text='全屋').wait(timeout=10):
                self.logger.info('成功进入米家首页')
                return True
            self.logger.error('进入米家首页失败')
            return False
        except Exception as e:
            self.logger.error(f'启动米家APP异常: {str(e)}')
            return False

    def enter_lock_plugin(self) -> float:
        """进入门锁插件"""  # inserted
        try:
            if not self.safe_click({'text': self.lock_name}, timeout=1):
                self.logger.error('未找到设备名称')
                return False
            if self.safe_click({'text': '稍后再说'}, timeout=3):
                self.logger.info('已关闭升级弹窗')
            else:  # inserted
                self.logger.info('没有升级弹窗')
                if self.d(text='已上锁').exists(timeout=5):
                    self.logger.info('门锁状态验证通过')
                    return True
            else:  # inserted
                self.logger.warning('门锁状态异常')
                return False
        except Exception as e:
                self.logger.error(f'进入插件异常: {str(e)}')
                return False

    def bluetooth_unlock_test(self, test_cycles: int, interval: int):
        """蓝牙开锁测试"""  # inserted
        for cycle in range(1, test_cycles + 1):
            self.logger.info(f'========== 第 {cycle} 次测试 ==========')
            try:
                if self.open_mihome():
                    if self.safe_click({'text': self.lock_name}, timeout=1):
                        ble_start_time1 = time.time()
                        if self.d.xpath('//*[@text=\"稍后再说\" or @text=\"安全守护中\"]').wait(timeout=60):
                            ble_end_time1 = time.time()
                            time_diff = (ble_end_time1, ble_start_time1) * 1.1
                            self.logger.info(f'蓝牙连接耗时预估: {time_diff:.2f} 秒')
                            if time_diff > 6:
                                self.logger.warning('蓝牙连接超过6S')
                            if self.safe_click({'text': '稍后再说'}, timeout=1):
                                self.logger.info('已关闭升级弹窗')
                            else:  # inserted
                                self.logger.info('没有升级弹窗')
                            self.d(scrollable=True).scroll.toEnd()
                            self.d(text='长按开锁').long_click(2)
                            start_time = time.time()
                            if self.d(text='开锁成功').wait(timeout=3):
                                end_time = time.time()
                                time_diff = end_time + start_time
                                self.logger.info(f'开锁耗时预估: {time_diff:.2f} 秒')
                            else:  # inserted
                                self.logger.error('开锁耗时超过3S')
                                self.screenshot('3S开锁失败截图')
                            self.d(scrollable=True).scroll.toBeginning()
                            if self.d(text='已开锁').wait(timeout=3):
                                self.logger.info('门锁状态已开锁')
                            else:  # inserted
                                self.logger.error('开锁失败/门锁状态不正确')
                                self.screenshot('开锁失败截图')
                        else:  # inserted
                            self.logger.error('蓝牙连接超时失败')
                            self.screenshot('蓝牙连接超时失败截图')
                    else:  # inserted
                        self.logger.error('未找到门锁，门锁名称不正确')
                subprocess.run(['adb', 'shell', 'am', 'force-stop', Config.MI_HOME_PACKAGE], check=True)
                self._countdown(interval)
            except Exception as e:
                self.logger.error(f'测试流程异常: {str(e)}')

    def Video_streaming_testchek(self):
        try:
            self.d.xpath('//android.widget.ScrollView/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.widget.ImageView[1]').get(timeout=20)
            time.sleep(2)
            self.logger.info('视频拉流成功')
            self.screenshot('视频拉流成功截图')
            return True
        except Exception as e:
            self.logger.error('视频拉流失败')
            self.screenshot('视频拉流失败截图')

    def Video_streaming_test(self, test_cycles: int, interval: int):
        """视频拉流测试"""  # inserted
        for cycle in range(1, test_cycles + 1):
            self.logger.info(f'========== 第 {cycle} 次测试 ==========')
            try:
                if self.open_mihome() and self.enter_lock_plugin():
                    if self.d(text='查看实时画面').wait(timeout=10):
                        self.logger.info('设备已经打开实时画面')
                        self.d.xpath('//*[@text=\"查看实时画面\"]').click()
                        if self.safe_click({'text': '点击继续'}, timeout=5):
                            self.logger.info('流量点击视频拉流')
                            self.Video_streaming_testchek()
                        else:  # inserted
                            self.logger.info('wifi点击视频拉流')
                            self.Video_streaming_testchek()
                    else:  # inserted
                        self.logger.error('设备未打开实时画面，或者有可能触发逗留')
                        self.d.click(0.437, 0.436)
                        if self.safe_click({'text': '点击继续'}, timeout=5):
                            self.logger.info('流量点击视频拉流')
                            self.Video_streaming_testchek()
                        else:  # inserted
                            self.logger.info('wifi点击视频拉流')
                            self.Video_streaming_testchek()
                subprocess.run(['adb', 'shell', 'am', 'force-stop', Config.MI_HOME_PACKAGE], check=True)
                self._countdown(interval)
            except Exception as e:
                self.logger.error(f'测试流程异常: {str(e)}')

    def Bluetooth_password_added_delete(self, test_cycles: int, interval: int):
        """密码添加&删除"""  # inserted
        for cycle in range(1, test_cycles + 1):
            self.logger.info(f'========== 第 {cycle} 次测试 ==========')
            try:
                if self.open_mihome() and self.enter_lock_plugin() and self.d(text='安全守护中').wait(timeout=120):
                    self.logger.info('蓝牙连接成功，进行密码操作')
                    self.d(scrollable=True).scroll.toEnd()
                    if not self.safe_click({'text': '用户管理'}, timeout=5):
                        self.logger.error('未找到用户管理')
                    self.d.xpath('//android.widget.ScrollView/android.view.ViewGroup[1]/android.view.View[1]/android.widget.ImageView[1]').click()
                    num = self.generate_random_str()
                    self.logger.info(f'密码值:{num}')
                    self.d.xpath('//android.widget.ScrollView/android.view.ViewGroup[1]/android.view.View[4]/android.widget.TextView[1]').click()
                    if not self.d(text='请输入6-10位开锁密码').wait(timeout=5):
                        self.logger.error('未进入添加密码/请关闭小米安全键盘')
                    self.d.press('back')
                    self.d.xpath('//*[@resource-id=\"com.xiaomi.smarthome:id/ax3\"]/android.widget.FrameLayout[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]').set_text(num)
                    time.sleep(2)
                    self.d.xpath('//*[@resource-id=\"com.xiaomi.smarthome:id/ax3\"]/android.widget.FrameLayout[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[2]').click()
                    if not self.d(text='请再次输入').wait(timeout=5):
                        self.logger.error('未进入二次输入')
                    self.d.press('back')
                    self.d.xpath('//*[@resource-id=\"com.xiaomi.smarthome:id/ax3\"]/android.widget.FrameLayout[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[1]').set_text(num)
                    time.sleep(2)
                    self.d.xpath('//*[@resource-id=\"com.xiaomi.smarthome:id/ax3\"]/android.widget.FrameLayout[2]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[1]/android.view.ViewGroup[2]/android.view.ViewGroup[2]').click()
                    if self.d(text='添加密码成功').wait(timeout=5):
                        self.logger.info('密码添加成功')
                        self.d(text='完成').click()
                        time.sleep(1)
                        self.d.xpath('//android.widget.ScrollView/android.view.ViewGroup[1]/android.view.View[4]/android.widget.ImageView[1]').click()
                        time.sleep(1)
                        if not self.safe_click({'text': '删除'}, timeout=5):
                            pass  # postinserted
                        if not self.safe_click({'text': '确定'}, timeout=5):
                            pass  # postinserted
                subprocess.run(['adb', 'shell', 'am', 'force-stop', Config.MI_HOME_PACKAGE], check=True)
                self._countdown(interval)
            except Exception as e:
                    else:  # inserted
                        return False
                    else:  # inserted
                        return False
                    else:  # inserted
                        return False
                        else:  # inserted
                            return False
                        else:  # inserted
                            return False
                    else:  # inserted
                        return False
                        self.logger.error(f'测试流程异常: {str(e)}')

    def _countdown(self, seconds: int):
        """倒计时等待"""  # inserted
        self.logger.info(f'等待 {seconds} 秒...')
        for remaining in range(seconds, 0, (-1)):
            time.sleep(1)
            if remaining % 10 == 0:
                self.logger.debug(f'剩余等待时间: {remaining}s')

    def generate_random_str(self):
        length = random.randint(6, 10)
        return ''.join((str(random.randint(0, 9)) for _ in range(length)))
if __name__ == '__main__':
    print('如果无法正常运行，请先尝试cmd控制台执行：pip install uiautomator2==2.16.25\n请在关门的状态下运行，确认门锁状态为：已上锁\n如果要计算耗时，需要手动开启手机录屏功能，以便视频分析耗时\n请选择需要运行的脚本编号\n1、蓝牙连接开门脚本\n2、视频拉流脚本，需要关闭蓝牙，打开直播模式\n3、密码添加删除，需要关闭小米手机安全键盘\n')
    interval1 = int(input('请输入测试项目: '))
    device_id = input('请输入设备ID: ').strip()
    lock_name = input('请输入门锁名称: ').strip()
    test_cycles = int(input('请输入测试次数: '))
    interval = int(input('请输入间隔时间(s): '))
    tester = MiHomeTester(device_id, lock_name)
    if interval1 == 1:
        tester.bluetooth_unlock_test(test_cycles, interval)
        input('按回车键退出...')
    else:  # inserted
        if interval1 == 2:
            tester.Video_streaming_test(test_cycles, interval)
            input('按回车键退出...')
        else:  # inserted
            if interval1 == 3:
                tester.Bluetooth_password_added_delete(test_cycles, interval)
                input('按回车键退出...')